package sharemem

import (
	"server_cluster/common/config"
	"server_cluster/common/gdconf"
	"server_cluster/common/logger"
	"server_cluster/common/protoc/pb"
	"sync/atomic"
)

type Talent struct {
	TalentId int32
	Level    int8
}

func (t *Talent) IsUse() bool {
	return t.TalentId != 0
}

type CaptainSkill struct {
	CaptainSkillGroup int32
	Level             int8
}

func (c *CaptainSkill) IsUse() bool {
	return c.CaptainSkillGroup != 0
}

type Role struct {
	Id                    MyInt32              // 角色id
	Level                 int16                // 等级
	Exp                   int32                // 经验
	Promote               int8                 // 等阶
	Star                  int8                 // 星级
	TalentList            [50]Talent           // 已解锁天赋列表
	CurrEnergy            int32                // 当前怒气值
	CurrHp                int32                // 当前生命值
	CaptainSkillList      [3]CaptainSkill      // 已解锁队长技能列表
	EquipList             [10]int32            // 装备列表 在线数据
	FightPropOverrideList [10]gdconf.FightProp // 战斗属性重写列表 在线数据
	Weapon                uint64               // 武器 在线数据
}

func (r *Role) MemInit() {
	r.Id.NewVal = 0
	r.Id.OldVal = 0
	r.Id.Status = 0
	r.Level = 0
	r.Exp = 0
	r.Promote = 0
	r.Star = 0
	for i := 0; i < len(r.TalentList); i++ {
		r.TalentList[i].TalentId = 0
		r.TalentList[i].Level = 0
	}
	r.CurrEnergy = 0
	r.CurrHp = 0
	for i := 0; i < len(r.CaptainSkillList); i++ {
		r.CaptainSkillList[i].CaptainSkillGroup = 0
		r.CaptainSkillList[i].Level = 0
	}
	for i := 0; i < len(r.EquipList); i++ {
		r.EquipList[i] = 0
	}
	for i := 0; i < len(r.FightPropOverrideList); i++ {
		r.FightPropOverrideList[i].PropId = 0
		r.FightPropOverrideList[i].PropValue = 0
	}
	r.Weapon = 0
}

func (r *Role) IsUse() bool {
	return r.Id.NewVal != 0 || r.Id.OldVal != 0
}

func (r *Role) GetId() int32 {
	return r.Id.NewVal
}

func (r *Role) SetSync() {
	atomic.AddUint32(&(r.Id.Status), 1)
}

func (r *Role) CreateRole(cfg *gdconf.RoleConfig) {
	r.Id.NewVal = cfg.RoleId
	r.Level = 1 // 角色初始1级
	r.Exp = 0
	r.Promote = 1 // 角色初始1阶
	r.Star = 0
}

func (r *Role) AddTalent(talentId int32) bool {
	for i := 0; i < len(r.TalentList); i++ {
		talent := &(r.TalentList[i])
		if talent.IsUse() {
			continue
		}
		talent.TalentId = talentId
		talent.Level = 1
		return true
	}
	logger.Error("no empty talent found")
	return false
}

func (r *Role) GetTalent(talentId int32) *Talent {
	for i := 0; i < len(r.TalentList); i++ {
		talent := &(r.TalentList[i])
		if !talent.IsUse() {
			break
		}
		if talent.TalentId == talentId {
			return talent
		}
	}
	return nil
}

func (r *Role) GetTalentList() []*Talent {
	talentList := make([]*Talent, 0)
	for i := 0; i < len(r.TalentList); i++ {
		talent := &(r.TalentList[i])
		if !talent.IsUse() {
			break
		}
		talentList = append(talentList, talent)
	}
	return talentList
}

func (r *Role) AddCaptainSkill(captainSkillGroup int32) bool {
	for i := 0; i < len(r.CaptainSkillList); i++ {
		captainSkill := &(r.CaptainSkillList[i])
		if captainSkill.IsUse() {
			continue
		}
		captainSkill.CaptainSkillGroup = captainSkillGroup
		captainSkill.Level = 1
		return true
	}
	logger.Error("no empty captain skill found")
	return false
}

func (r *Role) GetCaptainSkill(captainSkillGroup int32) *CaptainSkill {
	for i := 0; i < len(r.CaptainSkillList); i++ {
		captainSkill := &(r.CaptainSkillList[i])
		if !captainSkill.IsUse() {
			break
		}
		if captainSkill.CaptainSkillGroup == captainSkillGroup {
			return captainSkill
		}
	}
	return nil
}

func (r *Role) GetCaptainSkillList() []*CaptainSkill {
	captainSkillList := make([]*CaptainSkill, 0)
	for i := 0; i < len(r.CaptainSkillList); i++ {
		captainSkill := &(r.CaptainSkillList[i])
		if !captainSkill.IsUse() {
			break
		}
		captainSkillList = append(captainSkillList, captainSkill)
	}
	return captainSkillList
}

func (r *Role) GetTalentEffectModifierList() []*gdconf.EffectModifier {
	effectModifierList := make([]*gdconf.EffectModifier, 0)
	for _, talent := range r.GetTalentList() {
		roleTalentConfig := gdconf.GetRoleTalentConfig(talent.TalentId)
		if roleTalentConfig == nil {
			continue
		}
		roleTalentEffectGroupConfig := gdconf.GetRoleTalentEffectGroupConfigByGroupAndLevel(roleTalentConfig.EffectGroup, int32(talent.Level))
		if roleTalentEffectGroupConfig == nil {
			continue
		}
		effectModifierList = append(effectModifierList, roleTalentEffectGroupConfig.EffectModifierList...)
	}
	return effectModifierList
}

func (u *User) GetUserRoleFightProp(roleId int32) map[int32]int32 {
	var role = u.GetRoleById(roleId)
	if role == nil {
		return nil
	}
	return u.getUserRoleFightProp(role, 0)
}

func (u *User) GetUserRoleFightProp4Trail(role *Role, trailId int32) map[int32]int32 {
	return u.getUserRoleFightProp(role, trailId)
}

// GetUserRoleFightProp 获取角色战斗属性
func (u *User) getUserRoleFightProp(role *Role, trailId int32) map[int32]int32 {

	fightPropMap := make(map[int32]int32)
	fightPropBaseMap := make(map[int32]int32)
	fightPropPercentMap := make(map[int32]int32)

	if trailId != 0 {
		var trailRoleConfig = gdconf.GetTrailRoleConfig4TrailId(trailId)
		if trailRoleConfig == nil {
			return nil
		}
		for _, fightProp := range trailRoleConfig.FightPropList {
			fightPropMap[fightProp.PropId] = fightProp.PropValue
			fightPropBaseMap[fightProp.PropId] = fightProp.PropValue
		}
	} else {
		roleConfig := gdconf.GetRoleConfig(role.GetId())
		if roleConfig == nil {
			return nil
		}
		roleLevelConfig := gdconf.GetRoleLevelConfigByGroupAndLevel(roleConfig.LevelGroup, int32(role.Level))
		if roleLevelConfig == nil {
			return nil
		}
		promoteConfig := gdconf.GetRolePromoteConfigByGroupAndPromote(roleConfig.PromoteGroup, int32(role.Promote))
		if promoteConfig == nil {
			return nil
		}
		// 攻防血
		for _, fightProp := range roleLevelConfig.FightPropList {
			fightPropMap[fightProp.PropId] = fightProp.PropValue
			fightPropBaseMap[fightProp.PropId] = fightProp.PropValue
		}
		// 充能效率 暴击 防御穿透 元素属性加减伤
		for _, fightProp := range roleConfig.FightPropList {
			fightPropMap[fightProp.PropId] = fightProp.PropValue
			fightPropBaseMap[fightProp.PropId] = fightProp.PropValue
		}
		for _, fightPropAdd := range promoteConfig.FightPropList {
			_, exist := fightPropMap[fightPropAdd.PropId]
			if !exist {
				logger.Error("fight prop not exist, fightPropId: %v", fightPropAdd.PropId)
				continue
			}
			switch fightPropAdd.AddType {
			case gdconf.FightPropAddTypeValue:
				fightPropMap[fightPropAdd.PropId] += fightPropAdd.PropValue
			case gdconf.FightPropAddTypePercent:
				fightPropPercentMap[fightPropAdd.PropId] += fightPropAdd.PropValue
			}
		}
	}

	// 天赋增加战斗属性
	for _, talent := range role.GetTalentList() {
		roleTalentConfig := gdconf.GetRoleTalentConfig(talent.TalentId)
		if roleTalentConfig == nil {
			continue
		}
		roleTalentEffectGroupConfig := gdconf.GetRoleTalentEffectGroupConfigByGroupAndLevel(roleTalentConfig.EffectGroup, int32(talent.Level))
		if roleTalentEffectGroupConfig == nil {
			continue
		}
		for _, fightPropAdd := range roleTalentEffectGroupConfig.FightPropAddList {
			_, exist := fightPropMap[fightPropAdd.PropId]
			if !exist {
				logger.Error("fight prop not exist, fightPropId: %v", fightPropAdd.PropId)
				continue
			}
			switch fightPropAdd.AddType {
			case gdconf.FightPropAddTypeValue:
				fightPropMap[fightPropAdd.PropId] += fightPropAdd.PropValue
			case gdconf.FightPropAddTypePercent:
				fightPropPercentMap[fightPropAdd.PropId] += fightPropAdd.PropValue
			}
		}
	}
	roleConfig := gdconf.GetRoleConfig(role.GetId())
	if roleConfig == nil {
		return nil
	}
	//星级提升额外增加属性 类型1
	roleStarConfig := gdconf.GetRoleStarConfigByGroupAndStar(roleConfig.StarGroup, int32(role.Star))
	if roleStarConfig == nil {
		return nil
	}
	for _, v := range roleStarConfig.ExtraAttrList {
		switch v.ExtraType {
		case gdconf.ExtraAttrType_AddNum:
			switch v.AttrPlusType {
			case 1:
				{
					fightPropMap[v.AttrType] += v.AttrValue
					fightPropBaseMap[v.AttrType] += v.AttrValue
				}
			case 2:
				{
					fightPropPercentMap[v.AttrType] += v.AttrValue
				}
			}
		}
	}
	// 装备增加战斗属性
	for _, equip := range u.GetUserRoleEquipListByPtr(role) {
		equipLevelConfig := gdconf.GetConfigEquipLevelByGroupAndLevel(equip.LevelGroup, int32(equip.Level))
		if equipLevelConfig == nil {
			logger.Error("get equipLevelConfig is nil, group: %v, level: %v, uid: %v", equip.LevelGroup, equip.Level, u.GetUid())
			continue
		}
		// 主属性
		fightPropAdd := equipLevelConfig.FightPropAdd
		if fightPropAdd == nil {
			continue
		}
		_, exist := fightPropMap[fightPropAdd.PropId]
		if !exist {
			logger.Error("fight prop not exist, fightPropId: %v, uid: %v", fightPropAdd.PropId, u.GetUid())
			continue
		}
		switch fightPropAdd.AddType {
		case config.ADD_FIGHT_PROP_TYPE_VALUE, config.ADD_FIGHT_PROP_TYPE_CLIENT_PERCENT:
			fightPropMap[fightPropAdd.PropId] += fightPropAdd.PropValue
		case config.ADD_FIGHT_PROP_TYPE_PERCENT:
			fightPropPercentMap[fightPropAdd.PropId] += fightPropAdd.PropValue
		}
		// // 副属性
		// for _, equipAffix := range equip.AffixList {
		// 	if equipAffix.AffixId == 0 {
		// 		break
		// 	}
		// 	_, exist := fightPropMap[equipAffix.PropId]
		// 	if !exist {
		// 		logger.Error("fight prop not exist, fightPropId: %v, uid: %v", equipAffix.PropId, u.GetUid())
		// 		continue
		// 	}
		// 	switch equipAffix.PropAddType {
		// 	case config.ADD_FIGHT_PROP_TYPE_VALUE, config.ADD_FIGHT_PROP_TYPE_CLIENT_PERCENT:
		// 		fightPropMap[equipAffix.PropId] += equipAffix.PropValue
		// 	case config.ADD_FIGHT_PROP_TYPE_PERCENT:
		// 		fightPropPercentMap[equipAffix.PropId] += equipAffix.PropValue
		// 	}
		// }
	}

	// 技能
	equipSkillList := u.GetEquipSkillList(u.GetUserRoleEquipListByPtr(role))
	for _, equipSkillConfig := range equipSkillList {
		fightProp := equipSkillConfig.FightPropAdd
		if fightProp == nil {
			continue
		}
		_, exist := fightPropMap[fightProp.PropId]
		if !exist {
			logger.Error("fight prop not exist, fightPropId: %v", fightProp.PropId)
			continue
		}
		switch fightProp.AddType {
		case gdconf.FightPropAddTypeValue:
			fightPropMap[fightProp.PropId] += fightProp.PropValue
		case gdconf.FightPropAddTypePercent:
			fightPropPercentMap[fightProp.PropId] += fightProp.PropValue
		}
	}

	// 武器增加战斗属性
	weapon := u.GetUserRoleWeaponByPtr(role)
	if weapon != nil {
		weaponConfig := gdconf.GetWeaponConfig(weapon.ItemId)
		if weaponConfig == nil {
			return nil
		}
		weaponLevelConfig := gdconf.GetWeaponLevelConfigByGroupAndLevel(weaponConfig.LevelGroup, int32(weapon.Level))
		if weaponLevelConfig == nil {
			return nil
		}
		for _, fightProp := range weaponLevelConfig.FightPropAddList {
			_, exist := fightPropMap[fightProp.PropId]
			if !exist {
				logger.Error("fight prop not exist, fightPropId: %v, uid: %v", fightProp.PropId, u.GetUid())
				continue
			}
			switch fightProp.AddType {
			case gdconf.FightPropAddTypeValue:
				fightPropMap[fightProp.PropId] += fightProp.PropValue
			case gdconf.FightPropAddTypePercent:
				fightPropPercentMap[fightProp.PropId] += fightProp.PropValue
			}
		}
		weaponPromoteConfig := gdconf.GetWeaponPromoteConfigByGroupAndPromote(weaponConfig.PromoteGroup, int32(weapon.Promote))
		if weaponPromoteConfig == nil {
			return nil
		}
		for _, fightProp := range weaponPromoteConfig.FightPropList {
			_, exist := fightPropMap[fightProp.PropId]
			if !exist {
				logger.Error("fight prop not exist, fightPropId: %v, uid: %v", fightProp.PropId, u.GetUid())
				continue
			}
			switch fightProp.AddType {
			case gdconf.FightPropAddTypeValue:
				fightPropMap[fightProp.PropId] += fightProp.PropValue
			case gdconf.FightPropAddTypePercent:
				fightPropPercentMap[fightProp.PropId] += fightProp.PropValue
			}
		}
		weaponStarConfig := gdconf.GetWeaponStarConfigByGroupAndStar(weaponConfig.StarGroup, int32(weapon.Star))
		if weaponStarConfig == nil {
			return nil
		}
		for _, fightProp := range weaponStarConfig.Attribute {
			_, exist := fightPropMap[fightProp.PropId]
			if !exist {
				logger.Error("fight prop not exist, fightPropId: %v, uid: %v", fightProp.PropId, u.GetUid())
				continue
			}
			switch fightProp.AddType {
			case gdconf.FightPropAddTypeValue:
				fightPropMap[fightProp.PropId] += fightProp.PropValue
			case gdconf.FightPropAddTypePercent:
				fightPropPercentMap[fightProp.PropId] += fightProp.PropValue
			}
		}
	}
	// 百分比加成
	for k, v := range fightPropPercentMap {
		fightPropMap[k] += int32(float32(fightPropBaseMap[k]) * float32(v) / 10000.0)
	}
	// 战斗属性重写
	for _, fightProp := range role.FightPropOverrideList {
		if fightProp.PropId == 0 {
			break
		}
		fightPropMap[fightProp.PropId] = fightProp.PropValue
	}
	//星级提升额外提升属性类型2
	for _, v := range roleStarConfig.ExtraAttrList {
		switch v.ExtraType {
		case gdconf.ExtraAttrType_CritRate2CritDamage:
			var criticalVal = fightPropMap[config.FIGHT_PROP_CRITICAL]
			var extraCriticalHurtVal = criticalVal * v.AttrValue / 10000.0
			fightPropMap[config.FIGHT_PROP_CRITICAL_HURT] += extraCriticalHurtVal
		case gdconf.ExtraAttrType_Speed2ATK:
			var criticalVal = fightPropMap[config.FIGHT_PROP_SPEED]
			var extraCriticalHurtVal = criticalVal * v.AttrValue / 10000.0
			fightPropMap[config.FIGHT_PROP_ATTACK] += extraCriticalHurtVal
		}

	}
	return fightPropMap
}

// GetCodexRoleFightProp 获取图鉴角色战斗属性
func (u *User) GetCodexRoleFightProp(roleId int32, isMax bool) map[int32]int32 {
	roleLevel := 0
	roleConfig := gdconf.GetRoleConfig(roleId)
	if roleConfig == nil {
		return nil
	}
	if !isMax {
		roleLevel = 1
	} else {
		for i := 1; i < 1000; i++ {
			ok := gdconf.CheckRoleLevelConfigByGroupAndLevel(roleConfig.LevelGroup, int32(i))
			if !ok {
				break
			}
			roleLevel = i
		}
	}
	roleLevelConfig := gdconf.GetRoleLevelConfigByGroupAndLevel(roleConfig.LevelGroup, int32(roleLevel))
	if roleLevelConfig == nil {
		return nil
	}
	fightPropMap := make(map[int32]int32)
	fightPropBaseMap := make(map[int32]int32)
	fightPropPercentMap := make(map[int32]int32)
	// 攻防血
	for _, fightProp := range roleLevelConfig.FightPropList {
		fightPropMap[fightProp.PropId] = fightProp.PropValue
		fightPropBaseMap[fightProp.PropId] = fightProp.PropValue
	}
	// 充能效率 暴击 防御穿透 元素属性加减伤
	for _, fightProp := range roleConfig.FightPropList {
		fightPropMap[fightProp.PropId] = fightProp.PropValue
		fightPropBaseMap[fightProp.PropId] = fightProp.PropValue
	}
	// 百分比加成
	for k, v := range fightPropPercentMap {
		fightPropMap[k] += int32(float32(fightPropBaseMap[k]) * float32(v) / 1000.0)
	}
	return fightPropMap
}

func (u *User) PacketUserRoleEquipList(roleId int32) []*pb.Equip {
	ret := make([]*pb.Equip, 0)
	for _, equip := range u.GetUserRoleEquipList(roleId) {
		ret = append(ret, PacketEquip(equip, u))
	}
	return ret
}

func (u *User) GetUserRoleEquipList(roleId int32) []*Equip {
	ret := make([]*Equip, 0)
	role := u.GetRoleById(roleId)
	if role == nil {
		logger.Error("get role is nil, roleId: %v, uid: %v", roleId, u.GetUid())
		return nil
	}
	for _, equipKey := range role.EquipList {
		if equipKey == 0 {
			continue
		}
		equip := u.GetEquip4Key(equipKey)
		if equip == nil {
			logger.Error("get equip is nil, equipKey: %v, uid: %v", equipKey, u.GetUid())
			continue
		}
		ret = append(ret, equip)
	}
	return ret
}

func (u *User) GetUserRoleEquipListByPtr(role *Role) []*Equip {
	ret := make([]*Equip, 0)
	for _, equipKey := range role.EquipList {
		if equipKey == 0 {
			continue
		}
		equip := u.GetEquip4Key(equipKey)
		if equip == nil {
			logger.Error("get equip is nil, equipKey: %v, uid: %v", equipKey, u.GetUid())
			continue
		}
		ret = append(ret, equip)
	}
	return ret
}

func (u *User) GetUserRoleWeapon(roleId int32) *Weapon {
	role := u.GetRoleById(roleId)
	if role == nil {
		logger.Error("get role is nil, roleId: %v, uid: %v", roleId, u.GetUid())
		return nil
	}
	return u.GetWeaponByKey(role.Weapon)
}

func (u *User) GetUserRoleWeaponByPtr(role *Role) *Weapon {
	return u.GetWeaponByKey(role.Weapon)
}

func (u *User) GetCaptainSkill() int32 {
	role := u.GetRoleById(u.UserActivity.CaptainSkillRoleId)
	if role == nil {
		return 0
	}
	captainSkill := role.GetCaptainSkill(u.UserActivity.CaptainSkillGroup)
	if captainSkill == nil {
		return 0
	}
	captainSkillLevelConfig := gdconf.GetCaptainSkillLevelConfigByGroupAndLevel(captainSkill.CaptainSkillGroup, int32(captainSkill.Level))
	if captainSkillLevelConfig == nil {
		return 0
	}
	return captainSkillLevelConfig.CaptainSkill
}

func (r *Role) AddExp(totalAddExp int32) int32 {
	roleConfig := gdconf.GetRoleConfig(r.GetId())
	if roleConfig == nil {
		return config.CONFIG_NOT_FOUND
	}

	rolePromoteConfig := gdconf.GetRolePromoteConfigByGroupAndPromote(roleConfig.PromoteGroup, int32(r.Promote))
	if rolePromoteConfig == nil {
		return config.CONFIG_NOT_FOUND
	}

	newExp := r.Exp
	newLevel := r.Level
	newExp += totalAddExp
	// 角色升级
	for i := 0; i < 1000; i++ {
		// 获取角色当前等级配置表
		ok := gdconf.CheckRoleLevelConfigByGroupAndLevel(roleConfig.LevelGroup, int32(newLevel))
		if !ok {
			break
		}
		roleLevelConfig := gdconf.GetRoleLevelConfigByGroupAndLevel(roleConfig.LevelGroup, int32(newLevel))
		if roleLevelConfig == nil {
			break
		}
		// 角色当前等级未突破则跳出循环
		if newLevel >= int16(rolePromoteConfig.LevelLimit) {
			// 角色未突破溢出的经验处理
			newExp = 0
			break
		}
		// 角色经验小于升级所需的经验则跳出循环
		if newExp < roleLevelConfig.Exp {
			break
		}
		// 角色等级提升
		newExp -= roleLevelConfig.Exp
		newLevel++
	}
	r.Level = newLevel
	r.Exp = newExp
	r.SetSync()
	return config.OK
}

func (r *Role) PreAddExp(totalAddExp int32) int32 {
	roleConfig := gdconf.GetRoleConfig(r.GetId())
	if roleConfig == nil {
		return config.CONFIG_NOT_FOUND
	}

	rolePromoteConfig := gdconf.GetRolePromoteConfigByGroupAndPromote(roleConfig.PromoteGroup, int32(r.Promote))
	if rolePromoteConfig == nil {
		return config.CONFIG_NOT_FOUND
	}

	newExp := r.Exp
	newLevel := r.Level
	newExp += totalAddExp
	// 角色升级
	for i := 0; i < 1000; i++ {
		// 获取角色当前等级配置表
		ok := gdconf.CheckRoleLevelConfigByGroupAndLevel(roleConfig.LevelGroup, int32(newLevel))
		if !ok {
			break
		}
		roleLevelConfig := gdconf.GetRoleLevelConfigByGroupAndLevel(roleConfig.LevelGroup, int32(newLevel))
		if roleLevelConfig == nil {
			break
		}
		// 角色当前等级未突破则跳出循环
		if newLevel >= int16(rolePromoteConfig.LevelLimit) {
			// 角色未突破溢出的经验处理
			return newExp
		}
		// 角色经验小于升级所需的经验则跳出循环
		if newExp < roleLevelConfig.Exp {
			break
		}
		// 角色等级提升
		newExp -= roleLevelConfig.Exp
		newLevel++
	}
	return 0
}

func (u *User) PacketUserRole(role *Role) *pb.User_Role {
	var pbWeapon *pb.Weapon = nil
	weapon := u.GetUserRoleWeapon(role.GetId())
	if weapon != nil {
		pbWeapon = u.PacketWeapon(weapon)
	}
	return &pb.User_Role{
		Id:           role.GetId(),
		Level:        int32(role.Level),
		Exp:          role.Exp,
		Promote:      int32(role.Promote),
		Star:         int32(role.Star),
		UnlockTalent: u.PacketUserRoleTalentList(role),
		FightPropMap: u.GetUserRoleFightProp(role.GetId()),
		EquipList:    u.PacketUserRoleEquipList(role.GetId()),
		Weapon:       pbWeapon,
	}
}

func (u *User) PacketUserRoleTalentList(role *Role) []*pb.Talent {
	ret := make([]*pb.Talent, 0)
	for _, talent := range role.GetTalentList() {
		talentConfig := gdconf.GetRoleTalentConfig(talent.TalentId)
		if talentConfig == nil {
			continue
		}
		ret = append(ret, &pb.Talent{
			TalentId:    talent.TalentId,
			TalentGroup: talentConfig.TalentGroup,
			Level:       int32(talent.Level),
		})
	}
	return ret
}

func (u *User) PacketUserRoleCaptainSkillData() *pb.SC_CaptainSkillDataNtf {
	captainSkillMap := make(map[int32]*pb.CaptainSkillList)
	for _, role := range u.GetRoleMap() {
		pbUnlockSkillList := make([]*pb.CaptainSkill, 0)
		for _, captainSkill := range role.GetCaptainSkillList() {
			pbUnlockSkillList = append(pbUnlockSkillList, &pb.CaptainSkill{
				CaptainSkillGroup: captainSkill.CaptainSkillGroup,
				Level:             int32(captainSkill.Level),
			})
		}
		if len(pbUnlockSkillList) == 0 {
			continue
		}
		captainSkillMap[role.GetId()] = &pb.CaptainSkillList{UnlockSkillList: pbUnlockSkillList}
	}
	return &pb.SC_CaptainSkillDataNtf{
		CaptainSkillMap:    captainSkillMap,
		CaptainRoleId:      u.UserActivity.CaptainRoleId,
		CaptainSkillRoleId: u.UserActivity.CaptainSkillRoleId,
		CaptainSkillGroup:  u.UserActivity.CaptainSkillGroup,
	}
}

func (u *User) PackUserRoleAll(rsp *pb.SC_Fetch) {
	rsp.Role = make([]*pb.User_Role, 0, len(u.GetRoleMap()))
	for _, role := range u.GetRoleMap() {
		rsp.Role = append(rsp.Role, u.PacketUserRole(role))
	}
}
